/*
Copyright [2020] [https://www.xiaonuo.vip]

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Snowy采用APACHE LICENSE 2.0开源协议，您在使用过程中，需要注意以下几点：

1.请不要删除和修改根目录下的LICENSE文件。
2.请不要删除和修改Snowy源码头部的版权声明。
3.请保留源码和相关描述文件的项目出处，作者声明等。
4.分发源码时候，请注明软件出处 https://gitee.com/xiaonuobase/snowy
5.在修改包名，模块名称，项目代码等时，请注明软件出处 https://gitee.com/xiaonuobase/snowy
6.若您的项目无法满足以上几点，可申请商业授权，获取Snowy商业授权许可，请在官网购买授权，地址为 https://www.xiaonuo.vip
 */
package vip.xiaonuo.modular.workroute.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import vip.xiaonuo.core.context.login.LoginContextHolder;
import vip.xiaonuo.core.exception.ServiceException;
import vip.xiaonuo.core.factory.PageFactory;
import vip.xiaonuo.core.pojo.page.PageResult;
import vip.xiaonuo.core.util.PoiUtil;
import vip.xiaonuo.modular.pro.entity.Pro;
import vip.xiaonuo.modular.pro.service.ProService;
import vip.xiaonuo.modular.workstep.entity.WorkStep;
import vip.xiaonuo.modular.workstep.service.WorkStepService;
import vip.xiaonuo.modular.worksteproute.entity.WorkStepRoute;
import vip.xiaonuo.modular.workroute.entity.WorkRoute;
import vip.xiaonuo.modular.workroute.enums.WorkRouteExceptionEnum;
import vip.xiaonuo.modular.workroute.mapper.WorkRouteMapper;
import vip.xiaonuo.modular.workroute.param.WorkRouteParam;
import vip.xiaonuo.modular.workroute.service.WorkRouteService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import vip.xiaonuo.modular.worksteproute.service.WorkStepRouteService;
import vip.xiaonuo.util.AutoCode;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 工艺路线service接口实现类
 *
 * @author bwl
 * @date 2022-05-24 15:33:25
 */
@Service
public class WorkRouteServiceImpl extends ServiceImpl<WorkRouteMapper, WorkRoute> implements WorkRouteService {

    @Resource
    private  WorkStepRouteService stepRouteService;
    @Resource
    private  WorkStepService workStepService;
    @Resource
    private ProService proService;

    @Override
    public PageResult<WorkRoute> page(WorkRouteParam workRouteParam) {
        QueryWrapper<WorkRoute> queryWrapper = new QueryWrapper<>();
        if (ObjectUtil.isNotNull(workRouteParam)) {

            // 根据编码 查询
            if (ObjectUtil.isNotEmpty(workRouteParam.getCode())) {
                queryWrapper.lambda().like(WorkRoute::getCode, workRouteParam.getCode());
            }
            // 根据工艺路线名称 查询
            if (ObjectUtil.isNotEmpty(workRouteParam.getName())) {
                queryWrapper.lambda().like(WorkRoute::getName, workRouteParam.getName());
            }
            // 根据备注 查询
            if (ObjectUtil.isNotEmpty(workRouteParam.getRemarks())) {
                queryWrapper.lambda().like(WorkRoute::getRemarks, workRouteParam.getRemarks());
            }
        }
        queryWrapper.orderByDesc("create_time");
        Page<WorkRoute> page=this.page(PageFactory.defaultPage(), queryWrapper);
        /*
         * ===============================================处理数据的准备工作 start ======================================
         */
        // 查询出所有工艺路线关系表数据
        List<WorkStepRoute> workStepRouteList = stepRouteService.list();
        // 按照工艺路线进行分组
        Map<Long,List<WorkStepRoute>> workStepRouteGroupByWorkRouteId = workStepRouteList.stream()
                .collect(Collectors.groupingBy(WorkStepRoute::getWorkRouteId));
        /*
         * ===============================================处理数据的准备工作 end ======================================
         */
        /*
         * ======================================= 给工艺路线关系list赋值 start =====================================
         */
        // 获取分页返回的所有工艺路线数据
        page.getRecords().forEach(item->{

            Long id = item.getId();
            if(ObjectUtil.isEmpty(id)){
                return;
            }
            List<WorkStepRoute> workStepRoutes = workStepRouteGroupByWorkRouteId.get(item.getId());
            if (ObjectUtil.isEmpty(workStepRoutes)){
                return;
            }
            // 排序
            ListUtil.sortByProperty(workStepRoutes, "sortNum");

            item.setWorkStepRouteList(workStepRoutes);
        });
        /*
         * ======================================= 给工艺路线关系list赋值 end =====================================
         */
        return new PageResult<>(page);
    }

    @Override
    public List<WorkRoute> list(WorkRouteParam workRouteParam) {
        List<WorkRoute> workRoutes=this.list();
        // 查询出所有工艺路线关系表数据
        List<WorkStepRoute> workStepRouteList = stepRouteService.list();
        if(ObjectUtil.isEmpty(workStepRouteList)){
            throw new ServiceException(10,"请先添加工艺路线");
        }
        // 按照工艺路线进行分组
        Map<Long,List<WorkStepRoute>> workStepRouteGroupByWorkRouteId = workStepRouteList.stream()
                .collect(Collectors.groupingBy(WorkStepRoute::getWorkRouteId));

        //查询工艺路线关系中有的工序id所对应的工序数据
        List<Long> workStepIds = workStepRouteList.stream().map(WorkStepRoute::getWorkStepId).collect(Collectors.toList());
        List<WorkStep> workSteps = workStepService.listByIds(workStepIds);
        //去重
        workSteps = workSteps.stream().distinct().collect(Collectors.toList());
        //按照工序id转map(value为不良品项)
        Map<Long,String> workStepsGroupByorkStepId =  workSteps.stream().collect(Collectors.toMap(WorkStep::getId, WorkStep::getMulBadItem));

        /*
         * ======================================= 给工艺路线关系list赋值 start =====================================
         */
        workRoutes.forEach(item->{

            Long id = item.getId();
            if(ObjectUtil.isEmpty(id)){
                return;
            }
            List<WorkStepRoute> workStepRoutes = workStepRouteGroupByWorkRouteId.get(item.getId());
            if (ObjectUtil.isEmpty(workStepRoutes)){
                return;
            }
            //添加工序对应不良品项
            workStepRoutes.forEach(workStepRoute->{
                workStepRoute.setMulBadItem(workStepsGroupByorkStepId.get(workStepRoute.getWorkStepId()));
            });
            // 排序
            ListUtil.sortByProperty(workStepRoutes, "sortNum");

            item.setWorkStepRouteList(workStepRoutes);
        });
        /*
         * ======================================= 给工艺路线关系list赋值 end =====================================
         */
        return workRoutes;
    }
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void add(WorkRouteParam workRouteParam) {
        /*
         *  ================================= 工艺路线数据处理 start =================================
         */
        //默认编码规则
        if(ObjectUtil.isEmpty(workRouteParam.getCode()))
        {

            //SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmssSSS");
            workRouteParam.setCode(AutoCode.getCodeByService("dw_work_route", this.getClass(), 0));

        }
        //校验参数，检查是否存在相同的名称和编码
        checkParam(workRouteParam, false);

        WorkRoute workRoute = new WorkRoute();
        BeanUtil.copyProperties(workRouteParam, workRoute);
        Boolean flag= this.save(workRoute);
        /*
         *  ================================= 工艺路线数据处理 end =================================
         */
        /*
         *  ================================= 工艺路线关系数据处理 start =================================
         */
        //判断添加工艺路线是否成功
        if (ObjectUtil.isNotEmpty(workRoute.getId()) && flag)
        {   //添加工艺路线id
            for (WorkStepRoute workStepRoute : workRouteParam.getList())
            {
                workStepRoute.setWorkRouteId(workRoute.getId());
            }
            //保存工艺路线关系
            stepRouteService.saveBatch(workRouteParam.getList());
        }else
        {
            throw new ServiceException(WorkRouteExceptionEnum.CRAFT_ROUTE_ADD_fAIL);
        }
        /*
         *  ================================= 工艺路线关系数据处理 end=================================
         */
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(List<WorkRouteParam> workRouteParamList) {
        // TODO 删除校验
        verifiDelete(workRouteParamList);
        //同时删掉工艺路线关系表
        QueryWrapper<WorkStepRoute> queryWrapper = new QueryWrapper<>();
        QueryWrapper<WorkRoute> workRouteQueryWrapper = new QueryWrapper<>();
        workRouteParamList.forEach(workRouteParam -> {
            workRouteQueryWrapper.lambda().eq(WorkRoute::getId,workRouteParam.getId()).or();
            queryWrapper.lambda().eq(WorkStepRoute::getWorkRouteId, workRouteParam.getId()).or();
        });
        stepRouteService.remove(queryWrapper);
        this.remove(workRouteQueryWrapper);
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public void edit(WorkRouteParam workRouteParam) {
        /*
         *  ================================= 工艺路线数据处理 start =================================
         */
        //校验参数，检查是否存在相同的名称和编码
        checkParam(workRouteParam, true);
        WorkRoute workRoute = this.queryWorkRoute(workRouteParam);
        BeanUtil.copyProperties(workRouteParam, workRoute);
        this.updateById(workRoute);
        /*
         *  ================================= 工艺路线数据处理 end =================================
         */
        /*
         *  ================================= 工艺路线关系数据处理 start =================================
         */
        //查询该工艺路线下关系表数据
        QueryWrapper<WorkStepRoute> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(WorkStepRoute::getWorkRouteId,workRouteParam.getId());
        List<WorkStepRoute> workStepRouteList=stepRouteService.list(queryWrapper);
        //取出数据库关系表id
        List<Long> dbids = workStepRouteList.stream().map(WorkStepRoute::getId).collect(Collectors.toList());
        //取出参数里的关系表id
        List<Long> pramids = workRouteParam.getList().stream().map(WorkStepRoute::getId).collect(Collectors.toList());
        //定义容器
        List<WorkStepRoute> editlist=new ArrayList<WorkStepRoute>();
        List<Long> deleteIdlist=new ArrayList<Long>();
        List<WorkStepRoute> addlist=new ArrayList<WorkStepRoute>();
        //循环判断
        for (WorkStepRoute workStepRoute : workRouteParam.getList())
        {
            //是否有id，如果没有则为新增数据
            if(ObjectUtil.isNotEmpty(workStepRoute.getId()))
            {   //id存在，修改
                workStepRoute.setWorkRouteId(workRoute.getId());
                editlist.add(workStepRoute);
            }else {
                //id不存在，新增
                workStepRoute.setWorkRouteId(workRoute.getId());
                addlist.add(workStepRoute);
            }
        }
        //比较编辑数据id与数据库数据id差异（数据库中有编辑中没有则删除）
        dbids.forEach(item->{
            if( !pramids.contains(item))
            {

                deleteIdlist.add(item);
            }
        });
        //批量新增
        if(ObjectUtil.isNotEmpty(addlist))
        {
            stepRouteService.saveBatch(addlist);
        }
        //批量删除
        if(ObjectUtil.isNotEmpty(deleteIdlist))
        {
            stepRouteService.removeByIds(deleteIdlist);
        }
        //批量修改
        if(ObjectUtil.isNotEmpty(editlist))
        {
            stepRouteService.updateBatchById(editlist);
        }

        /*
         *  ================================= 工艺路线关系数据处理 end=================================
         */

    }

    @Override
    public WorkRoute detail(WorkRouteParam workRouteParam) {
        return this.queryWorkRoute(workRouteParam);
    }

    /**
     * 获取工艺路线
     *
     * @author bwl
     * @date 2022-05-24 15:33:25
     */
    private WorkRoute queryWorkRoute(WorkRouteParam workRouteParam) {
        WorkRoute workRoute = this.getById(workRouteParam.getId());
        if (ObjectUtil.isNull(workRoute)) {
            throw new ServiceException(WorkRouteExceptionEnum.NOT_EXIST);
        }
        return workRoute;
    }

    @Override
    public void export(WorkRouteParam workRouteParam) {
        List<WorkRoute> list = this.list(workRouteParam);
        PoiUtil.exportExcelWithStream("SnowyWorkRoute.xls", WorkRoute.class, list);

    }

    /**
     * 根据节点id获取所有子节点id集合
     *
     * @author bwl
     * @date 2020/3/26 10.43
     */
    private List<Long> getChildIdListById(Long id) {
        List<Long> childIdList = CollectionUtil.newArrayList();
        LambdaQueryWrapper<WorkRoute> queryWrapper = new LambdaQueryWrapper<>();

//        queryWrapper.like(WorkRoute::getPids, SymbolConstant.LEFT_SQUARE_BRACKETS + id +
//                SymbolConstant.RIGHT_SQUARE_BRACKETS);

        this.list(queryWrapper).forEach(workRoute -> childIdList.add(workRoute.getId()));

        return childIdList;
    }

    /**
     * 获取工艺路线表
     *
     * @author bwl
     * @date 2022-05-27 10:40
     */
    private WorkRoute queryProType(WorkRouteParam workRouteParam) {
        WorkRoute workRoute = this.getById(workRouteParam.getId());
        if (ObjectUtil.isNull(workRoute)) {
            throw new ServiceException(WorkRouteExceptionEnum.NOT_EXIST);
        }
        return workRoute;
    }


    /**
     * 校验参数，检查是否存在相同的名称和编码
     *
     * @author bwl
     * @date 2020/5/25 12:23
     */
    private void checkParam(WorkRouteParam workRouteParam, boolean isExcludeSelf) {
        LambdaQueryWrapper<WorkRoute> queryWrapperByCode = new LambdaQueryWrapper<>();

        String name = workRouteParam.getName();
        String code = workRouteParam.getCode();
        //校验排除
        if (isExcludeSelf)
        {
            Long id = workRouteParam.getId();
            queryWrapperByCode.ne(WorkRoute::getId,id);
        }
        queryWrapperByCode.eq(WorkRoute::getCode, code);
        int countByCode = this.count(queryWrapperByCode);
        if (countByCode >= 1) {
            throw new ServiceException(WorkRouteExceptionEnum.ORG_CODE_REPEAT);
        }

        LambdaQueryWrapper<WorkRoute> queryWrapperByName = new LambdaQueryWrapper<>();

        if (isExcludeSelf) {
            Long id = workRouteParam.getId();
            queryWrapperByName.ne(WorkRoute::getId,id);
        }

        queryWrapperByName.eq(WorkRoute::getName, name);

        queryWrapperByName.eq(WorkRoute::getCode, code);
        int countByName = this.count(queryWrapperByName);

        if (countByName >= 1) {
            throw new ServiceException(WorkRouteExceptionEnum.ORG_NAME_REPEAT);
        }

    }
    /**
     * 删除校验
     * @author bwl
     * @date 2020/5/25 12:23
     */
    private void verifiDelete(List<WorkRouteParam> workRouteParamList) {
        List<Long> workRouteIds = new ArrayList<Long>();
        workRouteParamList.forEach(workRouteParam -> {
            workRouteIds.add(workRouteParam.getId());
        });
        QueryWrapper<Pro> proQueryWrapper = new QueryWrapper<>();
        proQueryWrapper.lambda().in(Pro::getWorkRouteId,workRouteIds);
        int countByCode = proService.count(proQueryWrapper);
        if (countByCode >= 1) {
            throw new ServiceException(5,"已有工艺路线绑定产品,请先删除产品");
        }
    }

}

